home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / Open Transport 1.3 / Open Transport SDK / Open Tpt Client Developer / Samples / Internet / OTMulticastPitchSample.cp < prev    next >
Encoding:
Text File  |  1998-04-30  |  10.2 KB  |  438 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        OTMulticastPitchSample.cp
  3.  
  4.     Contains:    IP Multicast under UDP sample.
  5.  
  6.     Copyright:    © 1993-1996 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10. #ifndef __OPENTPTGLOBALNEW__
  11. #include <OpenTptGlobalNew.h>
  12. #endif
  13.  
  14. #include <OpenTptInternet.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <Quickdraw.h>
  19.  
  20. /*******************************************************************************
  21. ** Misc defines
  22. ********************************************************************************/
  23.  
  24. const UInt8        kDefaultTTL = 3;            // Normal IP multicast default is 1.
  25.  
  26. /*******************************************************************************
  27. ** Globals
  28. ********************************************************************************/
  29.  
  30. char            gMulticastAddrStr[] = "235.1.2.3";
  31. InetPort        gMulticastPort = 2345;
  32. InetHost        gMulticastHost;
  33. InetAddress        gMulticastAddr;
  34. EndpointRef        gEndpt;
  35. char            gMessage[256];
  36.  
  37. /*******************************************************************************
  38. ** SetupMulticast
  39. ********************************************************************************/
  40.  
  41. OSStatus SetupMulticast()
  42. {
  43.     TEndpointInfo    info;
  44.     OSStatus        err = kOTNoError;
  45.     TBind            req;
  46.     InetAddress        myAddr;
  47.  
  48.     fprintf(stderr, "The program will send packets on port <%d>\n", gMulticastPort);
  49.  
  50.     do
  51.     {
  52.         //
  53.         //    Get a UDP endpoint which can be used for IP Multicast sends and receives
  54.         //
  55.         
  56.         gEndpt = OTOpenEndpoint(OTCreateConfiguration(kUDPName), 0, &info, &err);
  57.         if ( gEndpt == NULL || err != kOTNoError )
  58.         {
  59.             fprintf(stderr, "ERROR: OpenEndpoint(UDP) failed with error <%d>\n", err);
  60.             break;
  61.         }
  62.                 
  63.         //
  64.         //    Set up an Inet Address for the multicast group 
  65.         //    using our multicast address string and defined port number.
  66.         //
  67.         
  68.         OTInetStringToHost(gMulticastAddrStr, &gMulticastHost);
  69.         OTInitInetAddress(&gMulticastAddr, gMulticastPort, gMulticastHost);
  70.     
  71.         //
  72.         //    Do a normal bind to any IP address on our system,
  73.         //    but use the multicast port so we can receive loopbacks at times.
  74.         //    OK to use req for both input and output.
  75.         //
  76.         
  77.         OTInitInetAddress(&myAddr, gMulticastPort, 0);
  78.         req.addr.len = sizeof(myAddr);
  79.         req.addr.maxlen = sizeof(myAddr);
  80.         req.addr.buf = (unsigned char *) &myAddr;
  81.         err = gEndpt->Bind(&req, &req);
  82.         if ( err != kOTNoError )
  83.         {
  84.             fprintf(stderr, "ERROR: Bind() failed with error <%d>\n", err);
  85.             break;
  86.         }
  87.     
  88.         //
  89.         //    Let IP know to listen for this multicast IP address on all interfaces.
  90.         //    
  91.         
  92.         TOptMgmt             optReq;
  93.         UInt8                 optBuffer[ kOTOptionHeaderSize + sizeof(TIPAddMulticast) ];
  94.         TOption*             opt = (TOption*)optBuffer;
  95.         TIPAddMulticast*    addopt = (TIPAddMulticast*)opt->value; 
  96.         
  97.         optReq.flags = T_NEGOTIATE;
  98.         optReq.opt.len = sizeof(optBuffer);
  99.         optReq.opt.buf = (UInt8*) optBuffer;
  100.         
  101.         opt->level = INET_IP;
  102.         opt->name = IP_ADD_MEMBERSHIP;
  103.         opt->len = sizeof(optBuffer);
  104.         
  105.         addopt->multicastGroupAddress = gMulticastHost;
  106.         addopt->interfaceAddress = kOTAnyInetAddress;
  107.         
  108.         err = gEndpt->OptionManagement(&optReq, &optReq);
  109.         if ( err != kOTNoError )
  110.         {
  111.             fprintf(stderr, "ERROR: OTOptionManagement() (add membership) failed with %d\n", err);
  112.             break;
  113.         }
  114.     
  115.         //
  116.         //    Setup time-to-live for multicast sends (defaults to 1)
  117.         //    Can reuse the TOptMgmt, but not Option itself is different.
  118.         //    While we could reuse the buffer above, I'll do it right to 
  119.         //    demonstrate correctness.
  120.         //
  121.  
  122.         UInt8                 ttlOptBuffer[ kOTOneByteOptionSize ];
  123.         TOption*             ttlOpt = (TOption*)ttlOptBuffer;
  124.         
  125.         optReq.flags = T_NEGOTIATE;
  126.         optReq.opt.len = sizeof(ttlOptBuffer);
  127.         optReq.opt.buf = (UInt8*) ttlOptBuffer;
  128.         
  129.         ttlOpt->level = INET_IP;
  130.         ttlOpt->name = IP_MULTICAST_TTL;
  131.         ttlOpt->len = sizeof(ttlOptBuffer);
  132.         *(char*)(ttlOpt->value) = kDefaultTTL;
  133.         
  134.         err = gEndpt->OptionManagement(&optReq, &optReq);
  135.         if ( err != kOTNoError )
  136.         {
  137.             fprintf(stderr, "ERROR: OTOptionManagement() (set ttl) failed with %d\n", err);
  138.             break;
  139.         }
  140.         
  141.         //
  142.         //    Put the endpoint into nonblocking mode so we don't hang
  143.         //    when receiving messages in synchronous mode.
  144.         //
  145.         
  146.         err = gEndpt->SetNonBlocking();
  147.         if ( err != kOTNoError )
  148.         {
  149.             fprintf(stderr, "ERROR: SetNonBlocking() failed with %d\n", err);
  150.             break;
  151.         }
  152.     } while (false);
  153.     return ( err != kOTNoError );
  154. }
  155.  
  156. Boolean gLoopbackState = true;
  157.  
  158. void LoopbackToggle()
  159. {
  160.     OSStatus err;
  161.     
  162.     gLoopbackState = !gLoopbackState;
  163.     if ( gLoopbackState )
  164.         fprintf(stderr, "Loopback on\n");
  165.     else
  166.         fprintf(stderr, "Loopback off\n");
  167.  
  168.     //    
  169.     //    Turn off loopback - unless you want to receive your own packets back.
  170.     //
  171.  
  172.     TOptMgmt     optReq;
  173.     UInt8         optBuffer[ kOTOneByteOptionSize ];
  174.     TOption*    opt = (TOption*)optBuffer;
  175.     
  176.     optReq.flags     = T_NEGOTIATE;
  177.     optReq.opt.len     = sizeof(optBuffer);
  178.     optReq.opt.buf     = (UInt8*) optBuffer;
  179.     
  180.     opt->level             = INET_IP;
  181.     opt->name             = IP_MULTICAST_LOOP;
  182.     opt->len             = sizeof(optBuffer);
  183.     *(char *)(opt->value) = gLoopbackState;
  184.     
  185.     err = gEndpt->OptionManagement(&optReq, &optReq);
  186.     if ( err != kOTNoError )
  187.     {
  188.         fprintf(stderr, "ERROR: OTOptionManagement() (loopback toggle) failed with %d\n", err);
  189.     }
  190. }
  191.  
  192.  
  193. void Cleanup()
  194. {
  195.     gEndpt->Close();
  196. }
  197.  
  198. void RecvLoop()
  199. {
  200.     /* 
  201.      * This loop receives all messages waiting on the stream.
  202.      * It operates in synchronous but nonblocking mode.
  203.      * If there are no messages waiting, we go get another one to send.
  204.      * Loopback messages (when the toggle is one) will be received too.
  205.      */
  206.     
  207.     OSStatus    err;
  208.     TUnitData    unitdata;
  209.     InetAddress    addr;
  210.     OTFlags        flags;
  211.     char        remoteAddr[32];
  212.  
  213.     while (true)
  214.     {
  215.         OTMemzero(remoteAddr, sizeof(remoteAddr));
  216.         OTMemzero(gMessage, sizeof(gMessage));
  217.         unitdata.addr.maxlen = sizeof(addr);
  218.         unitdata.addr.buf = (unsigned char*) &addr;
  219.         unitdata.opt.maxlen = 0;
  220.         unitdata.opt.buf = 0;
  221.         unitdata.udata.maxlen = sizeof(gMessage);
  222.         unitdata.udata.buf = (UInt8*) gMessage;
  223.         err = gEndpt->RcvUData( &unitdata, &flags);
  224.         if ( err != kOTNoError )
  225.         {
  226.             if ( err == kOTNoDataErr )
  227.             {
  228.                 return;
  229.             }
  230.             else
  231.             {
  232.                 fprintf(stderr, "ERROR: RcvUData() failed with %d\n", err);
  233.                 break;
  234.             }
  235.         }
  236.         OTInetHostToString( addr.fHost, remoteAddr);
  237.         fprintf(stderr, "IP multicast from <%s>:%s\n", remoteAddr, gMessage);
  238.         fflush(stderr);
  239.     }
  240. }
  241.  
  242. void SendLoop()
  243. {
  244.     TUnitData    unitdata;
  245.     short        len;
  246.     Boolean        done = false;
  247.  
  248.     /* 
  249.      * This routine is a loop which will get one message for the user,
  250.      * send if via IP multicast, and then check for any received messages
  251.      * and print them out.
  252.      */
  253.     while ( !done )
  254.     {
  255.         OTMemzero(gMessage, sizeof(gMessage));
  256.         fprintf(stderr, "Message to send (hit return to quit)?\n");
  257.         gets((char *) gMessage);
  258.         len = OTStrLength((char *) gMessage);
  259.         if ( len != 0 )
  260.         {
  261.             unitdata.udata.len = len;
  262.             unitdata.udata.buf = (UInt8*) gMessage;
  263.             unitdata.opt.len = 0;
  264.             unitdata.opt.buf = NULL;
  265.             unitdata.addr.len = sizeof(gMulticastAddr);
  266.             unitdata.addr.buf = (unsigned char *)&gMulticastAddr;
  267.             gEndpt->SndUData( &unitdata);
  268.             RecvLoop();
  269.             LoopbackToggle();
  270.             fflush(stderr);
  271.         }
  272.         else
  273.             done = true;
  274.     }        
  275. }
  276.  
  277.  
  278. void ShowEndpointOptions()
  279. {
  280.     /*
  281.      *    This function retrieves and displays 
  282.      *    the IP and UDP endpoint options for this endpoint.
  283.      */
  284.      
  285.     OSStatus    err;
  286.     TOptMgmt*            ret = (TOptMgmt*)OTAlloc(gEndpt, T_OPTMGMT, T_OPT, &err);
  287.  
  288.     
  289.     do
  290.     {
  291.         fprintf(stderr, "Current Readable IP Option Settings for endpoint @ %08lX:\n", gEndpt);
  292.         if ( ret == NULL )
  293.         {
  294.             fprintf(stderr, "ERROR: could not allocate TOptMgmt structure (%d)\n", err);
  295.             break;
  296.         }
  297.         //
  298.         // Get the current IP options
  299.         //
  300.         TOptMgmt        req;
  301.         TOptionHeader    option;
  302.         
  303.         option.len        = kOTOptionHeaderSize;
  304.         option.level    = INET_IP;
  305.         option.name        = T_ALLOPT;
  306.         
  307.         req.opt.buf = (UInt8*)&option;
  308.         req.opt.len    = kOTOptionHeaderSize;
  309.         req.flags    = T_CURRENT;
  310.         
  311.         err = gEndpt->OptionManagement(&req, ret);
  312.         if ( err != kOTNoError )
  313.         {
  314.             fprintf(stderr, "ERROR: OptionManagement T_CURRENT request returned %d\n", err);
  315.             break;
  316.         }
  317.         //
  318.         // Now, let's print the options
  319.         //
  320.         {
  321.             TOption*    opt = (TOption*)ret->opt.buf;
  322.             char        string[512];
  323.  
  324.             err = OTCreateOptionString("ip", &opt, ret->opt.buf + ret->opt.len,
  325.                                        string, sizeof(string));
  326.             
  327.             if ( err == kOTNoError )
  328.             {
  329.                 char*    str = string;
  330.                 size_t    len = 0;
  331.                 while ( true )
  332.                 {
  333.                     char* temp = strchr(str, ',');
  334.                     if ( temp == NULL )
  335.                     {
  336.                         fprintf(stderr, "%s\n", str);
  337.                         break;
  338.                     }
  339.                     if ( len + temp - str + 1 > 80 )
  340.                     {
  341.                         fprintf(stderr, "\n");
  342.                         if ( *str == ' ' )
  343.                             str += 1;
  344.                         len = 0;
  345.                     }
  346.                     fprintf(stderr, "%*.*s", temp - str + 1, temp - str + 1, str);
  347.                     len += temp - str + 1;
  348.                     str = temp + 1;
  349.                 }
  350.             }
  351.         }
  352.         
  353.         TOption* opt =  OTFindOption(ret->opt.buf, ret->opt.len, INET_IP, IP_MULTICAST_TTL);
  354.             
  355.         if ( opt == NULL )
  356.             fprintf(stderr, "ERROR:OptionManagement did not have IP_MULTICAST_TTL in returned options\n");
  357.  
  358.         //
  359.         // Get the current UDP options
  360.         //
  361.         fprintf(stderr, "Current Readable UDP Option Settings for endpoint @ %08lX:\n", gEndpt);
  362.         option.len        = kOTOptionHeaderSize;
  363.         option.level    = INET_UDP;
  364.         option.name        = T_ALLOPT;
  365.         
  366.         req.opt.buf = (UInt8*)&option;
  367.         req.opt.len    = kOTOptionHeaderSize;
  368.         req.flags    = T_CURRENT;
  369.         
  370.         err = gEndpt->OptionManagement(&req, ret);
  371.         if ( err != kOTNoError )
  372.         {
  373.             fprintf(stderr, "ERROR: OptionManagement T_CURRENT request returned %d\n", err);
  374.             break;
  375.         }
  376.         //
  377.         // Now, let's print the options
  378.         //
  379.         {
  380.             TOption*    opt = (TOption*)ret->opt.buf;
  381.             char        string[512];
  382.  
  383.             err = OTCreateOptionString("udp", &opt, ret->opt.buf + ret->opt.len,
  384.                                        string, sizeof(string));
  385.             
  386.             if ( err == kOTNoError )
  387.             {
  388.                 char*    str = string;
  389.                 size_t    len = 0;
  390.                 while ( true )
  391.                 {
  392.                     char* temp = strchr(str, ',');
  393.                     if ( temp == NULL )
  394.                     {
  395.                         fprintf(stderr, "%s\n", str);
  396.                         break;
  397.                     }
  398.                     if ( len + temp - str + 1 > 80 )
  399.                     {
  400.                         fprintf(stderr, "\n");
  401.                         if ( *str == ' ' )
  402.                             str += 1;
  403.                         len = 0;
  404.                     }
  405.                     fprintf(stderr, "%*.*s", temp - str + 1, temp - str + 1, str);
  406.                     len += temp - str + 1;
  407.                     str = temp + 1;
  408.                 }
  409.             }
  410.         }
  411.         
  412.     } while ( false );
  413.     OTFree(ret, T_OPTMGMT);
  414. }
  415.  
  416.  
  417. void Inits()
  418. {
  419.     InitGraf(&qd.thePort);
  420.     if ( InitOpenTransport() != kOTNoError )
  421.     {
  422.         fprintf(stderr, "MulticastPitchSample: Could not initialize ASLM\n");
  423.         exit(1);
  424.     }
  425. }
  426.  
  427. void main()
  428. {
  429.     Inits();
  430.     if ( SetupMulticast() == kOTNoError )
  431.     {
  432.         ShowEndpointOptions();
  433.         SendLoop();
  434.         Cleanup();
  435.     }
  436. }
  437.  
  438.